unit RestoreUnit;

interface

uses
  Windows,
  SysUtils,
  Classes,
  JwaWinIoctl,
  WinSvc,
  Registry;

const
  WTDISK_CONTROL_DEVICE = '\\.\wtDiskCtrl';
  WTDISKV_CONTROL_DEVICE = '\\.\wtDiskVCtrl';
  FILE_DEVICE_WTDISKCTRL = $00008585;
  FILE_DEVICE_WTDISKVCTRL = $00008586;
  SYSTEM_PARAMETER_LOCATION	= 50;
  WTHY = 1465141337;


type
  SYSTEM_PARAMETER = packed record
    Tag: ULONG;
    remParameterVersion: ULONG;
    ProtectPartitionCount: UCHAR;
    DiskNO: array[0..25] of UCHAR;
    PartitionNO: array[0..25] of UCHAR;
    DriverLetter: array[0..25] of UCHAR;
    PartitionIsProtect: array[0..25] of UCHAR;
    PartitionIsDistill: array[0..25] of UCHAR;
    PassWord: array[0..31] of CHAR;
    StartProtect: UCHAR;
    Space: array[0..339] of UCHAR;
  end;
  PSYSTEM_PARAMETER = ^SYSTEM_PARAMETER;
  

  SYSTEM_STATE = packed record
    Tag: ULONG;
    remDrvVersion: ULONG;
    CurrentBufferCount: ULONG;
    AllBufferCount: ULONG;
    PartitionMemory: ULONG;
    ErrorCode: ULONG;
    ServiceStateActivation: ULONG;
  end;
  PSYSTEM_STATE = ^SYSTEM_STATE;


  USER_STORAGE_DEVICE_NUMBER = record
    DeviceType: ULONG;
    DeviceNumber: ULONG;
    PartitionNumber: ULONG;
  end;
  PUSER_STORAGE_DEVICE_NUMBER = ^USER_STORAGE_DEVICE_NUMBER;

  function IOCTL_RESYSTEM_PARAMETER_SET: DWORD;
  function IOCTL_RESYSTEM_PARAMETER_READ: DWORD;
  function IOCTL_RESYSTEM_STATE_READ: DWORD;
  
  function IOCTL_VDISK_GET_DISTILL_OBJECT_NAME: DWORD;
  function IOCTL_VDISK_CLOSE_DISTILL_OBJECT: DWORD;
//  begin
//    Result := CTL_CODE(FILE_DEVICE_WTDISKCTRL, $A8, 0, 0);
//  end;

  
function GetDiskAndPartitionNumbers(DriverLetter: Char; var DiskNum: ULONG; var PartNum: ULONG): Boolean;

procedure InstallUpFliters(ARegKey: string; ADriverName: string);
function InstallRestore(ARunParam: SYSTEM_PARAMETER): Boolean;
function IsDriverInstalled: Boolean;
function GetDistillDeviceObjectName: string;
function CloseDistillDeviceObject: Boolean;
function UninstallRetore: Boolean;

function ClearProtect: Boolean;
function SetProtect(AGameDrive: Char): Boolean;

procedure GetDrivers(Drivers: TStrings);

function GetRunState(Param: PSYSTEM_STATE): Boolean;

function SetRunParam(Param: PSYSTEM_PARAMETER): Boolean;


//procedure LogMenuMessage(AMessage: string);
procedure LogMessage(AMessage: string);
function GetSysDir: string;
function fcGetWindowsDir: string;

implementation

//uses FunctionUnit;

function GetSysDir: string;
var
  p: PChar;
begin
  p := AllocMem( MAX_PATH );
  try
    GetSystemDirectory(p, MAX_PATH);
    Result := IncludeTrailingPathDelimiter( p );
  finally
    FreeMem( p );
  end;

end;

function fcGetWindowsDir: string;
var
  buf: array[0..MAX_PATH - 1] of Char;
  len: DWORD;
begin
  len := SizeOf(buf);
  GetWindowsDirectory(@buf, len);
  Result := buf;
end;

procedure LogFile(AMsg: string; ALogFile: string);
var
  LogFile:  TextFile;
begin
  try
    ForceDirectories(ExtractFilePath(ALogFile));
    AssignFile(LogFile, ALogFile);
  
    if not FileExists(ALogFile) then
      Rewrite(LogFile)
    else
      Reset(LogFile);

    Append(LogFile);

    Writeln(LogFile, Format('[%s][%s] %s', [ DatetimeToStr(now),
                                             ExtractFileName(ChangeFileExt(ParamStr(0), '')),
                                             AMsg]) );

    CloseFile(LogFile);
  except
  end;
end;

//procedure LogMenuMessage(AMessage: string);
//begin
//  LogFile(AMessage, ExtractFilePath(ParamStr(0)) + 'Log\Client' + FormatDateTime('YYYYMMDD', Now) + '.log');
//end;

procedure LogMessage(AMessage: string);
begin
  LogFile(AMessage, ExtractFilePath(ParamStr(0)) + 'Log\' + FormatDateTime('YYYYMMDD', Now) + '.log');
end;


function IOCTL_RESYSTEM_PARAMETER_SET: DWORD;
begin
  Result := CTL_CODE(FILE_DEVICE_WTDISKCTRL, $A8, 0, 0);
end;

function IOCTL_RESYSTEM_PARAMETER_READ: DWORD;
begin
  Result := CTL_CODE(FILE_DEVICE_WTDISKCTRL, $A9, 0, 0);
end;

function IOCTL_RESYSTEM_STATE_READ: DWORD;
begin
  Result := CTL_CODE( FILE_DEVICE_WTDISKCTRL, $AA, 0,0)
end;

function IOCTL_VDISK_GET_DISTILL_OBJECT_NAME: DWORD;
begin
  Result:= CTL_CODE(FILE_DEVICE_WTDISKVCTRL, $901, METHOD_BUFFERED, FILE_READ_ACCESS or FILE_WRITE_ACCESS);
end;

function IOCTL_VDISK_CLOSE_DISTILL_OBJECT: DWORD;
begin
  Result := CTL_CODE(FILE_DEVICE_WTDISKVCTRL, $902, METHOD_BUFFERED, FILE_READ_ACCESS or FILE_WRITE_ACCESS);
end;


function GetDiskAndPartitionNumbers(DriverLetter: Char; var DiskNum: ULONG; var PartNum: ULONG): Boolean;
var
  FileHandle: THandle;
  deviceInfo: USER_STORAGE_DEVICE_NUMBER;
  bytesReturned: DWORD;
  DiskLetter: string;
begin
  Result := True;

  DiskLetter := Format('\\?\%s:', [DriverLetter]);
  FileHandle := CreateFile(PChar(DiskLetter),
                                 GENERIC_READ,
                                 FILE_SHARE_READ or FILE_SHARE_WRITE,
                                 nil,
                                 OPEN_EXISTING,
                                 FILE_ATTRIBUTE_NORMAL,
                                 0);
  if FileHandle = INVALID_HANDLE_VALUE then
  begin
    Result := False;
    Exit;
  end;

  bytesReturned := 0;
  if not DeviceIoControl(FileHandle,
                         IOCTL_STORAGE_GET_DEVICE_NUMBER,
                         nil,
                         0,
                         @deviceInfo,
                         SizeOf(deviceInfo),
                         bytesReturned,
                         nil) then
  begin
    CloseHandle(FileHandle);
    Result := False;
    Exit;
  end;

  if bytesReturned <> SizeOf(deviceInfo) then
  begin
    CloseHandle(FileHandle);
    Result := False;
    Exit;
  end;

  if deviceInfo.DeviceType <> 7 then
  begin
    Result := False;
    Exit;
  end;

  DiskNum := deviceInfo.DeviceNumber;
  PartNum := deviceInfo.PartitionNumber;
  CloseHandle(FileHandle);
end;

function InstallService(AServiceName, AServiceExt: string; AFlag, AStartType: DWORD): Boolean;
var
  hSCManager, hService: SC_HANDLE;
  TargetFile: string;
  reVal: Boolean;
  dwTagId: DWORD;
begin
  Result := True;
  dwTagId := AFlag;
  TargetFile := IncludeTrailingPathDelimiter(GetSysDir) + 'system32\drivers\' + AServiceName + '.' + AServiceExt;
  hSCManager := OpenSCManager(nil, nil, SC_MANAGER_ALL_ACCESS);
  if hSCManager <> 0 then
  begin
    hService := CreateService(hSCManager,
                              PChar(AServiceName),
                              PChar(AServiceName),
                              SERVICE_ALL_ACCESS,
                              SERVICE_KERNEL_DRIVER,
                              AStartType,
                              SERVICE_ERROR_NORMAL,
                              PChar(TargetFile),
                              'ReService',
                              @dwTagId,
                              nil, nil, nil);
    if hService = 0 then
    begin
      Result := False;
    end;
  end;

  CloseServiceHandle(hService);
  CloseServiceHandle(hSCManager);
end;


procedure InstallUpFliters(ARegKey: string; ADriverName: string);
var
  filters: array[0..MAX_PATH -1] of Char;
  i, htype, len: DWORD;
  str: string;
  hk: HKEY;
begin
  ZeroMemory(@filters, SizeOf(filters));
  with TRegistry.Create do
  try
    RootKey := HKEY_LOCAL_MACHINE;
    if not OpenKey(ARegKey, False) then

//    if RegOpenKey(HKEY_LOCAL_MACHINE, PChar(ARegKey), hk) <> ERROR_SUCCESS then
    begin
      LogMessage('RegOpenKey UpperFilters error');
      Exit;
    end;

    len := SizeOf(filters);
    if RegQueryValueEx(CurrentKey, 'UpperFilters', 0, @htype, @filters, @len) <> ERROR_SUCCESS then
    begin
      LogMessage('RegQueryValueEx UpperFilters error');
    end;

    SetLength(str, len);
    for i := 1 to len do
      str[i] := filters[i-1];
    if Pos(ADriverName, str) > 0 then
      Exit;

//    for i := 1 to Length(ADriverName) do
//      filters[len - 1 + i - 1] := ADriverName[i];
    CopyMemory(@filters[len-1], PChar(ADriverName), Length(ADriverName));
    len := len + Length(ADriverName);
    filters[len] := Chr(0);
    if RegSetValueEx(CurrentKey, 'UpperFilters', 0, htype, @filters, len + 1) <> ERROR_SUCCESS then
      LogMessage('RegSetvalueEx UpperFilters error');
  finally
    Free;
//    RegCloseKey(hk);
  end;

end;

function AddPassthroughFile: Boolean;
var
  SL: TStrings;
  str: string;
  i: Integer;
const
  PassKey  = 'SYSTEM\CurrentControlSet\Services\Tcpip\Parameters';
begin
  Result := False;
  SL := TStringList.Create;
  str := IncludeTrailingPathDelimiter(fcGetWindowsDir) + 'bootstat.dat';
  SL.Append(str);

  str := 'C:\PAGEFILE.sys';
  SL.Append(str);

  with TRegistry.Create do
  try
    RootKey := HKEY_LOCAL_MACHINE;
    OpenKey(PassKey, False);
    for i := 0 to 127 do
    begin
      DeleteKey(Format('Username%d', [i]));
    end;

    for i := 0 to SL.Count - 1 do
      WriteString(Format('Username%d', [i]), SL[i]);
  finally
    Free;
  end;
  Result := True;
end;

function SetRunParamWriteSector(Param: PSYSTEM_PARAMETER; IsCancel: Boolean): Boolean;
var
  Buffer: array[0..511] of Char;
  ref, Position: DWORD;
  hDisk: THandle;
begin
  Result := False;
  ZeroMemory(@buffer, SizeOf(Buffer));
  if not IsCancel then
  begin
    Param^.Tag := WTHY;
    CopyMemory(@Buffer, Param, 512);
//    Move(Param^, Buffer, 512);
  end;

  hDisk := CreateFile('\\.\PhysicalDrive0',
                      GENERIC_READ or GENERIC_WRITE,
                      FILE_SHARE_READ or FILE_SHARE_WRITE or FILE_SHARE_DELETE,
                      nil,
                      OPEN_EXISTING,
                      FILE_ATTRIBUTE_NORMAL,
                      0);

  if hDisk = INVALID_HANDLE_VALUE then
    Exit;

  Position := SetFilePointer(hDisk, SYSTEM_PARAMETER_LOCATION * 512, 0, FILE_BEGIN);
  if not WriteFile(hDisk, Buffer, 512, ref, nil) then
  begin
    CloseHandle(hDisk);
    Exit;
  end;
  CloseHandle(hDisk);
  Result := True;
end;

function SetRunParam(Param: PSYSTEM_PARAMETER): Boolean;
var
  hDevice: THandle;
  bytesReturned: DWORD;
  Buffer: array[0..511] of Char;
//  idx1, idx2: Integer;
  m_reI: ULONG;
begin
//  ARunParam.Tag := 'WTHY';
  Result := False;
  Param^.Tag := WTHY;
  hDevice := CreateFile(WTDISK_CONTROL_DEVICE,
                        GENERIC_READ or GENERIC_WRITE,
                        FILE_SHARE_READ or FILE_SHARE_WRITE or FILE_SHARE_DELETE,
                        nil,
                        OPEN_EXISTING,
                        FILE_ATTRIBUTE_NORMAL,
                        0);
  if (hDevice <> INVALID_HANDLE_VALUE) then
  begin
//    CopyMemory(@Buffer, Param, SizeOf(SYSTEM_PARAMETER));
//    LogMessage(Buffer);
    LogMessage(Format('SetRunParam DeviceIoControl, IOCTL_RESYSTEM_PARAMETER_SET: %d', [DWORD(IOCTL_RESYSTEM_PARAMETER_SET)]));
    DeviceIoControl(hDevice,
                    DWORD(IOCTL_RESYSTEM_PARAMETER_SET),
                    Param, SizeOf(SYSTEM_PARAMETER),
                    Param, SizeOf(SYSTEM_PARAMETER),
                    BytesReturned, nil);
    if (bytesReturned <> SizeOf(SYSTEM_PARAMETER)) then
    begin
      LogMessage('DeviceIOControl IOCTL_RESYSTEM_PARAMETER_SET failed');
      CloseHandle(hDevice);
      Exit;
    end;
    CloseHandle(hDevice);
  end
  else
  begin
    Result := SetRunParamWriteSector(Param, False);
    LogMessage(Format('SetRunParamWriteSector %s', [BoolToStr(Result, True)]));
    Exit;
  end;
  Result := True;
end;

function InstallRestore(ARunParam: SYSTEM_PARAMETER): Boolean;
begin
  Result := False;

//  if AInstallFile then
//  begin
    if not InstallService('wtdisk', 'sys', 0, SERVICE_BOOT_START) then
    begin
      LogMessage('InstallService wtdisk failed');
      Exit;
    end;

     InstallUpFliters('System\CurrentControlSet\Control\Class\{4D36E967-E325-11CE-BFC1-08002BE10318}', 'wtdisk');


    if not InstallService('wtdiskv', 'sys', 1, SERVICE_SYSTEM_START) then
    begin
      LogMessage('InstallService wtdiskv failed');
      Exit;
    end;

    if not AddPassthroughFile then
    begin
      LogMessage('AddpassthroughFile failed');
      Exit;
    end;
//  end;

  if not SetRunParam(@ARunParam) then
  begin
    LogMessage('SetRunParam failed');
    Exit;
  end;
  Result := True;
end;

function GetDistillDeviceObjectName: string;
var
  hVDiskCtrl: THandle;
  BytesReturned: DWORD;
  VDiskDeviceName: array[0..MAX_PATH - 1] of Char;
  ULen: DWORD;
begin
  Result := '';
  ZeroMemory(@VDiskDeviceName, MAX_PATH);
  ULen := SizeOf(VDiskDeviceName);
  hVDiskCtrl := CreateFile(WTDISKV_CONTROL_DEVICE,
                           GENERIC_READ or GENERIC_WRITE,
                           FILE_SHARE_READ, //or FILE_SHARE_WRITE or FILE_SHARE_DELETE,
                           nil,
                           OPEN_EXISTING,
                           FILE_ATTRIBUTE_NORMAL,
                           0);

  if hVDiskCtrl = INVALID_HANDLE_VALUE then
  begin
    LogMessage(Format('CreateFile %s, Failed', [WTDISKV_CONTROL_DEVICE]));
    Exit;
  end;

  if (not DeviceIoControl(hVDiskCtrl,
                         IOCTL_VDISK_GET_DISTILL_OBJECT_NAME,
                         nil,
                         0,
                         @VDiskDeviceName,
                         ULen,
                         BytesReturned,
                         nil)) or
    (BytesReturned <= 0) then
  begin
    LogMessage(Format('DeviceIOControl error, IOCTL_VDISK_GET_DISTILL_OBJECT_NAME, %s, %d', [VDiskDeviceName, BytesReturned]));
    CloseHandle(hVDiskCtrl);
    Exit;
  end;

  Result := VDiskDeviceName;   
end;

function CloseDistillDeviceObject: Boolean;
var
  hVDiskCtrl: THandle;
  BytesReturned: DWORD;
begin
  Result := False;
  hVDiskCtrl := CreateFile(WTDISKV_CONTROL_DEVICE,
                           GENERIC_READ or GENERIC_WRITE,
                           FILE_SHARE_READ,
                           nil,
                           OPEN_EXISTING,
                           FILE_ATTRIBUTE_NORMAL,
                           0);
  if hVDiskCtrl = INVALID_HANDLE_VALUE then
    Exit;

  if (not DeviceIoControl(hVDiskCtrl,
                          IOCTL_VDISK_CLOSE_DISTILL_OBJECT,
                          nil,
                          0,
                          nil,
                          0,
                          BytesReturned,
                          nil)) or
    (BytesReturned <= 0) then
  begin
    CloseHandle(hVDiskCtrl);
    Exit;
  end;

  CloseHandle(hVDiskCtrl);
  Result := True;
end;

function IsDriverInstalled: Boolean;
var
  hDevice: THandle;
begin
  Result := False;
  hDevice := CreateFile(WTDISK_CONTROL_DEVICE,
                        GENERIC_READ or GENERIC_WRITE,
                        FILE_SHARE_READ,
                        nil,
                        OPEN_EXISTING,
                        FILE_ATTRIBUTE_NORMAL,
                        0);
  if hDevice <> INVALID_HANDLE_VALUE then
  begin
    CloseHandle(hDevice);
    Result := True;
    Exit;
  end;
//  CloseHandle(hDevice);

  hDevice := CreateFile(WTDISKV_CONTROL_DEVICE,
                        GENERIC_READ or GENERIC_WRITE,
                        FILE_SHARE_READ,
                        nil,
                        OPEN_EXISTING,
                        FILE_ATTRIBUTE_NORMAL,
                        0);
  if hDevice = INVALID_HANDLE_VALUE then
    Exit;

  CloseHandle(hDevice);
  Result := True;
end;

function GetRunState(Param: PSYSTEM_STATE): Boolean;
var
  hDevice: THandle;
  BytesReturned: DWORD;
begin
  Result := False;
  ZeroMemory(Param, SizeOf(Param^));

  hDevice := CreateFile(WTDISK_CONTROL_DEVICE,
                        GENERIC_READ or GENERIC_WRITE,
                        FILE_SHARE_READ or FILE_SHARE_WRITE or FILE_SHARE_DELETE,
                        nil,
                        OPEN_EXISTING,
                        FILE_ATTRIBUTE_NORMAL,
                        0);

  if hDevice = INVALID_HANDLE_VALUE then
    Exit;

  BytesReturned := 0;
  DeviceIoControl(hDevice,
                  IOCTL_RESYSTEM_STATE_READ,
                  Param, SizeOf(SYSTEM_STATE),
                  Param, SizeOf(SYSTEM_STATE),
                  BytesReturned, nil);
  if BytesReturned <> SizeOf(SYSTEM_STATE) then
  begin
    CloseHandle(hDevice);
    ZeroMemory(Param, SizeOf(SYSTEM_STATE));
    Exit;
  end;

  Result := True;
end;

function UnInstallUpFliters(UpFilterKeyPath, UpFilterKeyAddDrv: string): Boolean;
var
  htype, len, position: DWORD;
  filters: array[0..MAX_PATH - 1] of Char;
  str: string;
  i: Integer;
begin
  Result := False;
  ZeroMemory(@filters, SizeOf(filters));

  with TRegistry.Create do
  try
    RootKey := HKEY_LOCAL_MACHINE;
    if not OpenKey(UpFilterKeyPath, False) then
    begin
      LogMessage('OpenKey UpperFilters error');
      Exit;
    end;

    len := SizeOf(filters);
    if ERROR_SUCCESS <> RegQueryValueEx(CurrentKey, 'UpperFilters', 0, @htype, @filters, @len) then
    begin
      LogMessage('RegQueryValueEx UpperFilters error');
      Exit;
    end;

    LogMessage(Format('UpperFilters Len: %d', [len]));
    SetLength(str, len);
    for i := 0 to len - 1 do
      str[i + 1] := filters[i];

    position := Pos(UpFilterKeyAddDrv, str);
    LogMessage(Format('UpperFilters Pos: %d', [position]));
    if position  = 0 then
      Exit;

    str := Copy(str, 1, position - 1) + Copy(str, position + Length(UpFilterKeyAddDrv) + 1, Length(str));
    LogMessage('UpperFilters str: ' + str);
    ZeroMemory(@filters, SizeOf(filters));

    for i := 1 to Length(str) do
      filters[i - 1] := str[i];

    len := len - (Length(UpFilterKeyAddDrv) + 1);
    Result := (RegSetValueEx(CurrentKey, 'UpperFilters', 0, htype, @filters, len) = ERROR_SUCCESS);
  finally
    Free;
  end;
end;

function GetRunParam(Param: PSYSTEM_PARAMETER): Boolean;
var
  hDevice: THandle;
  BytesReturned: DWORD;
  TmpParam: SYSTEM_PARAMETER;
begin
  ZeroMemory(@TmpParam, SizeOf(SYSTEM_PARAMETER));

  hDevice := CreateFile(WTDISK_CONTROL_DEVICE,
                        GENERIC_READ or GENERIC_WRITE,
                        FILE_SHARE_READ or FILE_SHARE_WRITE or FILE_SHARE_DELETE,
                        nil,
                        OPEN_EXISTING,
                        FILE_ATTRIBUTE_NORMAL,
                        0);
  BytesReturned := 0;
  if hDevice = INVALID_HANDLE_VALUE then
  begin
    Result := SetRunParamWriteSector(Param, False);
    Exit;
  end;

  DeviceIoControl(hDevice,
                  IOCTL_RESYSTEM_PARAMETER_READ,
                  @TmpParam, SizeOf(SYSTEM_PARAMETER),
                  @TmpParam, SizeOf(SYSTEM_PARAMETER),
                  BytesReturned, nil);
  if BytesReturned <> SizeOf(SYSTEM_PARAMETER) then
  begin
    CloseHandle(hDevice);
    Result := False;
    Exit;
  end;

  CopyMemory(Param, @TmpParam, SizeOf(TmpParam));
  CloseHandle(hDevice);
  Result := True;
end;

function ClearProtect: Boolean;
var
  TempParam: SYSTEM_PARAMETER;
  i: Integer;
begin
  Result := False;
  ZeroMemory(@TempParam, SizeOf(TempParam));
  if not GetRunParam(@TempParam) then
    Exit;

  LogMessage('ProtectCount: ' + IntToStr(TempParam.ProtectPartitionCount));
  for i := 0 to TempParam.ProtectPartitionCount - 1 do
  begin
    if TempParam.DriverLetter[i] = 0 then
      Continue;
    TempParam.PartitionIsProtect[i] := 0;
    TempParam.PartitionIsDistill[i] := 0;
  end;

  TempParam.ProtectPartitionCount := 0;

  Result := SetRunParam(@TempParam);
end;

function SetProtect(AGameDrive: Char): Boolean;
var
  TempParam: SYSTEM_PARAMETER;
  TempChar: Char;
  i: Integer;
  DiskNum, PartNum: ULONG;
begin
  Result := False;
  if not GetRunParam(@TempParam) then
    Exit;

  for i := Ord('C') to Ord('Z') do
  begin
    TempChar := Chr(i);
//    DriverDir := Format('%s:', [TempChar]);
    if GetDiskAndPartitionNumbers(TempChar, DiskNum, PartNum) then
    begin
      TempParam.DiskNO[TempParam.ProtectPartitionCount] := UCHAR(DiskNum);
      TempParam.PartitionNO[TempParam.ProtectPartitionCount] := UCHAR(PartNum);
      TempParam.DriverLetter[TempParam.ProtectPartitionCount] := UCHAR(TempChar);

//      if TempChar = 'C' then
      TempParam.PartitionIsProtect[TempParam.ProtectPartitionCount] := 1;

//      if TempChar = cbbBuffer.Text[1] then
//      begin
//        TempParam.PartitionIsProtect[TempParam.ProtectPartitionCount] := 1;
//      end;

      if TempChar = AGameDrive then
//        TempParam.PartitionIsProtect[TempParam.ProtectPartitionCount] := 1;
        TempParam.PartitionIsDistill[TempParam.ProtectPartitionCount] := 1;

      Inc(TempParam.ProtectPartitionCount);
    end;
  end;

//  TempParam.ProtectPartitionCount := 0;
  if not SetRunParam(@TempParam) then
    Exit;

  Result := True;
end;

function RemoveService(AServerName, AExt: string): Boolean;
var
  hSCManager, hService: SC_HANDLE;
  fn: string;
begin
  hSCManager := OpenSCManager(nil, nil, SC_MANAGER_ALL_ACCESS);
  if hSCManager <> 0 then
  begin
    hService := OpenService(hSCManager, PChar(AServerName), SERVICE_ALL_ACCESS);
    if hService <> 0 then
    begin
      DeleteService(hService);
      CloseServiceHandle(hService);
    end;
    CloseServiceHandle(hSCManager);
  end;
  fn := Format('%sDrivers\%s.%s', [GetSysDir, AServerName, AExt]);
  DeleteFile(fn);
  Result := True;
end;

function UninstallRetore: Boolean;
var
  i: Integer;
begin
  Result := False;
  if not ClearProtect then
    Exit;
  LogMessage('ClearProtect ok');
  with TRegistry.Create do
  try
    RootKey := HKEY_LOCAL_MACHINE;
    if not OpenKey('SYSTEM\CurrentControlSet\Services\Tcpip\Parameters', False) then
      Exit;
    for i := 0 to 127 do
      DeleteValue(Format('Username%d', [i]));
  finally
    Free;
  end;
  LogMessage('Delete passthough file registry ok');

  RemoveService('wtdisk', 'sys');
  LogMessage('RemoveService wtdisk ok');
  RemoveService('wtdiskv', 'sys');
  LogMessage('Removeservice wtdiskv ok');

  UnInstallUpFliters('System\CurrentControlSet\Control\Class\{4D36E967-E325-11CE-BFC1-08002BE10318}', 'wtdisk');
  LogMessage('Uninstall UpperFilters ok');
  RegDeleteKey(HKEY_LOCAL_MACHINE, 'SYSTEM\CurrentControlSet\Services\wtdisk');
  LogMessage('DeleteKey wtdisk ok');
  RegDeleteKey(HKEY_LOCAL_MACHINE, 'SYSTEM\CurrentControlSet\Services\wtdiskv');
  LogMessage('DeleteKey wtdiskv ok');
  Result := True;
end;

procedure GetDrivers(Drivers: TStrings);
var
  Drive: Char;
  DriveLetter: string;
begin
  if not Assigned(Drivers) then
    Exit;

  Drivers.Clear;
  for Drive := 'A' to 'Z' do
  begin
    DriveLetter := Drive + ':\';
    if GetDriveType(PChar(DriveLetter)) = DRIVE_FIXED then
      Drivers.Add(Drive);
  end;

end;

end.
